package com.hrt.serial.modbus;

import com.btcode.common.ByteUnit;

/**
 * modbus串口数据对象，用于处理粘包问题
 * 
 * @author gislin
 */
public class ModbusDataFrameDecoderRTU extends ModbusDataFrameDecoderBase {

    private final int msgMinLength = 3;
    
    public ModbusDataFrameDecoderRTU(byte[] msg) {
        this.msg = msg;
    }

    public byte[] next() {
        if (msg.length < msgMinLength) {
            throw new MsgLengthException("数据长度不足");
        }
        /**
         * 整个报文中，数据部分的字节长度 两个字节代表一个数据 所以数据字节长度和真正的业务数据长度不一样 数据字节长度是业务数据的两倍
         */
        int dataByteLength = ByteUnit.ConvertByteToInt8(msg[2]);
        /**
         * 1位从站编号，1位功能码，1位数据长度，n位数据，2位校验位 整个报文的字节长度
         */
        int expectMsgByteLength = 1 + 1 + 1 + dataByteLength + 2;

        if ((msg.length - readedPosition) < expectMsgByteLength) {
            throw new MsgLengthException("数据长度不足");
        }

        byte[] targetMsg = new byte[expectMsgByteLength];

        System.arraycopy(msg, readedPosition, targetMsg, 0, expectMsgByteLength);

        if (!ModbusCRCUnit.crcCheck(targetMsg)) {
            throw new CRCException("CRC验证不通过");
        }

        readedPosition += expectMsgByteLength;

        return targetMsg;
    }

}
